﻿using System;
using OpenTK;
using OpenTK.Graphics.OpenGL4;
namespace Common {
    public abstract class VboBase : GlDisposableObjectBase {
        public BufferTarget BufferTarget { get; protected set; }
        public int Id { get; protected set; }
        public BufferUsageHint UsageHint { get; set; }
        //int ElementCount { get; set; }
        public int ByteLength { get; set; }

    }
    public class Vbo<T> : VboBase where T : unmanaged {
        unsafe public Vbo(BufferTarget bufferTarget, BufferUsageHint usageHint, T[] data) {
            Id = GL.GenBuffer();
            this.BufferTarget = bufferTarget;
            this.UsageHint = usageHint;
            //this.ElementCount = data.Length;
            this.ByteLength = data.Length * sizeof(T);
            GL.BindBuffer(bufferTarget, Id);
            GL.BufferData(bufferTarget, sizeof(T) * data.Length, data, usageHint);
        }
        public Vbo(BufferTarget bufferTarget, BufferUsageHint usageHint, int size) {
            Id = GL.GenBuffer();
            this.BufferTarget = bufferTarget;
            this.UsageHint = usageHint;
            GL.BindBuffer(bufferTarget, Id);
            GL.BufferData(BufferTarget, size, IntPtr.Zero, usageHint);
        }
        public Vbo(T[] data, BufferTarget bufferTarget = BufferTarget.ArrayBuffer, BufferUsageHint usageHint = BufferUsageHint.StaticDraw) : this(bufferTarget, usageHint, data) {
        }
        //public Vbo() {
        //}
        //unsafe public Vbo(BufferTarget bufferTarget, BufferUsageHint usageHint, Vector3[] vector3s) {
        //    CreateBuffer(bufferTarget, usageHint, vector3s);
        //}
        //unsafe public void CreateBuffer<T>(BufferTarget bufferTarget, BufferUsageHint usageHint, T[] data) where T:unmanaged {
        //    Id = GL.GenBuffer();
        //    this.BufferTarget = bufferTarget;
        //    GL.BindBuffer(bufferTarget, Id);
        //    int size = sizeof(T) * data.Length;
        //    GL.BufferData(bufferTarget, size, data, usageHint);

        //}
        public unsafe void SetBufferData(T[] data) {
            GL.BindBuffer(BufferTarget.ArrayBuffer, this.Id);
            GL.BufferData(this.BufferTarget, sizeof(T) * data.Length, data, this.UsageHint);
        }
        public void Bind() {
            GL.BindBuffer(this.BufferTarget, this.Id);
        }
        protected override void OnDispose() {
            GL.DeleteBuffer(Id);
        }
    }
    public class Vbo : Vbo<float> {
        public Vbo(BufferTarget bufferTarget, BufferUsageHint usageHint, float[] data) : base(bufferTarget, usageHint, data) {
        }
        public Vbo(float[] data, BufferTarget bufferTarget = BufferTarget.ArrayBuffer, BufferUsageHint usageHint = BufferUsageHint.StaticDraw) : base(bufferTarget, usageHint, data) {
        }
    }
    public class Ibo<T> : Vbo<T> where T : unmanaged {
        public Ibo(T[] data, BufferTarget bufferTarget = BufferTarget.ElementArrayBuffer, BufferUsageHint usageHint = BufferUsageHint.StaticDraw) : base(bufferTarget, usageHint, data) {
        }
    }

}
